/**
 * @author Maripo GODA <avenafatua@gmail.com>
 * @helpUrl http://www.madin.jp/diary/?date=20091004#p02
 */
var map = null;

function stateUpdated(){
    if (map == null) {
        frameDoc = document.getElementById('canvasContainer').contentDocument;
        applyCss (frameDoc, 'http://www.madin.jp/gadget/index.css');
        setTimeout(prepareMap,500);
        //prepareMap();
    }
    else {
        var recentStr = wave.getState().get('mind_recent');
        if (recentStr) 
            map.execCommand(recentStr);
    }
}

var _loaded = false;

function main(){
    if (_loaded) 
        return;
    _loaded = true;
    if (wave) {
        wave.setStateCallback(stateUpdated);
    }
}

gadgets.util.registerOnLoadHandler(main);

var frameDoc = null;

function applyCss (doc,cssUrl) {
    var link = doc.createElement("link");
    link.setAttribute("rel", "stylesheet");
    link.setAttribute("href", cssUrl);
    link.setAttribute("type", "text/css");
    doc.getElementsByTagName('head')[0].appendChild(link);
}

function prepareMap(){
    
    var canvas = frameDoc.createElement('div');
    canvas.id = 'canvas';
    frameDoc.body.appendChild(canvas);
    
    var drawing = frameDoc.createElement('canvas');
    drawing.id = 'drawing';
    frameDoc.body.appendChild(drawing);
    
    var treeStr = (wave && wave.isInWaveContainer()) ? wave.getState().get('mind_tree') : null;
    map = new Brainstorming.Map({
        canvas: frameDoc.getElementById("canvas")
    });
    if (treeStr) {
        map.restoreFromDump(treeStr);
    }
    else {
        var node = map.createNodeFirst({
            text: "Map Title",
            position: {x: 220, y: 220}
        });
        map.render();
    }
}

var Brainstorming = {
    Node: {},
    Connector: {},
    Editor: {},
    Map: {},
    Util: {},
    ShapePicker: {}
};

/**
 * Map constructor
 */
Brainstorming.Map = function(params){
    this.mapInterfaceList = new Array();
    this.nodeMap = new Array();
    this.nodeIdSequence = 1;
    this.canvas = params.canvas;
        
    this.actorIcon = frameDoc.createElement('IMG');
    this.actorIcon.className = 'actorIcon';
    this.actorIcon.style.display = 'none';
    frameDoc.body.appendChild(this.actorIcon);
    this.lineArea = frameDoc.getElementById('drawing').getContext("2d");
    this.shapePicker = new Brainstorming.ShapePicker(this);
    this.colorPicker = new Brainstorming.ColorPicker(this);
    
    this.mouseMoveEvent = Brainstorming.Util.addEventListener(this.canvas, 'mousemove', this.getMouseMoveEvent());
    this.mouseUpEvent = Brainstorming.Util.addEventListener(frameDoc.body, 'mouseup', this.getOnMouseupEvent());
    Brainstorming.Util.addEventListener(window, 'resize', this.adjustSize());
};

Brainstorming.Map.prototype = {
    createNode: function(params){
        params.id = this.getNextNodeId();
        map.updateWave('create', params.id, params);
        
    },
    createNodeFirst: function(params){
        var node = new Brainstorming.Node(this, params);
        node.id = this.getNextNodeId();
        this.registerNode(node);
        if (this.root == null) 
            this.rootNode = node;
        return node;
    },
    resize: function () {
        var maxWidth = this.canvas.clientWidth;
        var maxHeight = this.canvas.clientHeight;
        var list = this.getNodeList();
        for (var i=0, l=list.length; i<l; i++) {
            var pos = list[i].getPositionMax();
            if (maxWidth < pos.x) maxWidth = pos.x;
            if (maxHeight < pos.y) maxWidth = pos.y;
        }
        this.canvas.style.width = maxWidth + 'px';
        this.canvas.style.height = maxHeight + 'px';
        frameDoc.getElementById('drawing').width = maxWidth;
        frameDoc.getElementById('drawing').height = maxHeight;    },
    adjustSize: function(){
        var self = this;
        return function(){
            frameDoc.getElementById('drawing').width = self.canvas.clientWidth;
            self.render();
        }
    },
    getNodeList: function () {
        var list = new Array();
        for (id in this.nodeMap) {
            if ('function' == typeof(this.nodeMap[id])) 
                continue;
            if (this.nodeMap[id] && !this.nodeMap[id].disposeFlg) 
                list.push(this.nodeMap[id]);
        }
        return list;
    },
    execCreateCommand: function(id, params){
        params.parentNode = this.nodeMap[params.parentNodeId];
        var node = new Brainstorming.Node(this, params);
        node.id = id;
        this.nodeIdSequence = id + 1;
        this.registerNode(node);
        if (this.root == null) 
            this.rootNode = node;
        if (node.parentNode) 
            node.parentNode.childNodes.push(node);
        node.render({
            canvas: this.canvas
        });
        return node;
        
    },
    getNextNodeId: function(){
        var max = 0;
        for (var _id in this.nodeMap) {
            var id = parseInt(_id);
            if (id > max) 
                max = id;
        }
        return max + 1;
    },
    restoreFromDump: function(treeStr){
        var nodeList = JSON.parse(treeStr);
        for (var i = 0, l = nodeList.length; i < l; i++) {
            var nodeObj = nodeList[i];
            if (nodeObj) 
                map.execCreateCommand(nodeObj.id, nodeObj);
        }
        map.render();
    },
    removeNode: function(){
        alert("Map.removeNode");
    },
    showShapePicker: function(node, onSelectCallback){
        this.shapePicker.show(node, onSelectCallback);
    },
    
    showColorPicker: function(node, onSelectCallback){
        this.colorPicker.show(node, onSelectCallback);
    },
    execUpdateCommand: function(param, caller){
        var targetNode = this.nodeMap[param.id];
        targetNode.update(param, caller);
        return targetNode;
    },
    onUpdateNode: function(node, caller){
    },
    
    registerNode: function(node){
        this.nodeMap[node.id] = node;
    },
    unregisterNode: function(node){
        this.nodeMap[node.id] = null;
    },
    refreshLines: function(){
        this.lineArea.clearRect(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
        this.nodeMap[1].drawLine();
    },
    startMove: function(node){
        this.moving = true;
        this.draggedNode = node;
        node.positionOrig = {
            x: node.position.x,
            y: node.position.y
        };
        this._draggingOffset = {
            x: this.draggedNode.position.x - this.position.x,
            y: this.draggedNode.position.y - this.position.y
        }
    },
    getMouseMoveEvent: function(){
        var self = this;
        return function(event){
        
            self.position = {
                x: event.clientX,
                y: event.clientY
            };
            if (!self.moving) 
                return;
            if (self.draggedNode) {
                self.draggedNode.setPosition({
                    x: self.position.x + self._draggingOffset.x,
                    y: self.position.y + self._draggingOffset.y
                });
            }
        }
    },
    render: function(){
        this.rootNode.render({
            canvas: this.canvas
        });
        this.resize();
        this.refreshLines();
    }
}

/**
 * Node constructor
 */
var DEFAULT_SHAPE_NAME = 'oval';

Brainstorming.Node = function(map, params){
    this.shape = DEFAULT_SHAPE_NAME;
    this.parentNode = params.parentNode;
    
    
    this.isRoot = !(this.parentNode);
    this.level = (this.parentNode) ? this.parentNode.level + 1 : 0;
    
    this.color = params.color || 'black';
    this.map = map;
    this.position = params.position || {x: 0,y: 0};
    this.text = params.text;
    this.shape = params.shape || DEFAULT_SHAPE_NAME;
    
    this.connector = new Brainstorming.Connector({
        from: this.parentNode,
        to: this,
        map: this.map,
        level: this.level
    });
    
    this._drawn = false;
    this._htmlElement = frameDoc.createElement('DIV');
    this._htmlElement.className = 'node ' + this.color + '_' + this.shape + Math.min(2, this.level);
    
    this._menuPalette = this.createMenuPalette();
    this._menuPalette.hide();
    this._htmlElement.appendChild(this._menuPalette);
    
    this._labelContainer = frameDoc.createElement('DIV');
    this._htmlElement.appendChild(this._labelContainer);
    this._label = this.getLabel();
    this._labelContainer.appendChild(this._label);
    this._editor = new Brainstorming.Editor(this);
    this._editor.hide();
    this._labelContainer.appendChild(this._editor._htmlElement);
    this.childNodes = new Array();
    
    Brainstorming.Util.addEventListener(this._htmlElement, 'mouseover', this.getOnMouseoverEvent());
    Brainstorming.Util.addEventListener(this._htmlElement, 'mouseout', this.getOnMouseoutEvent());
}

Brainstorming.Editor = function(node){
    this.node = node;
    this._htmlElement = frameDoc.createElement('DIV');
    this._input = frameDoc.createElement('INPUT');
    this._htmlElement.appendChild(this._input);
    var htmlElement = this._htmlElement;
    this._htmlElement.hide = function(){
        htmlElement.style.display = 'none';
    };
    this._htmlElement.show = function(){
        htmlElement.style.display = 'block';
    };
    this._htmlElement.appendChild(this.getUpdateIcon());
};
Brainstorming.Editor.prototype = {
    hide: function(){
        this._htmlElement.hide()
    },
    show: function(){
        this._input.value = this.node.text;
        this._htmlElement.show();
        this._input.focus();
    },
    getUpdateIcon: function(){
        var icon = frameDoc.createElement('INPUT');
	icon.type = 'button';
        icon.value = 'OK';
        var self = this;
        Brainstorming.Util.addEventListener(icon, 'click', function(){
            self.node.setText(self._input.value);
            self.hide();
        });
        return icon;
    }
};

Brainstorming.Node.prototype.createMenuPalette = function(){
    var palette = frameDoc.createElement('DIV');
    palette.className = 'menuPalette';
    palette.appendChild(this.createAddChildIcon());
    palette.appendChild(this.getEditIcon());
    palette.appendChild(this.createColorIcon());
    palette.appendChild(this.createShapeIcon());
    palette.appendChild(this.getDeleteIcon());
    
    var self = this;
    Brainstorming.Util.addEventListener(palette, 'mousedown', self.getOnMousedownEvent());
    
    palette.hide = function(){
        palette.style.visibility = 'hidden';
    };
    palette.show = function(){
        palette.style.visibility = 'visible';
    };
    return palette;
};
Brainstorming.Node.prototype.getPositionMax = function(){
    return {x:this.position.x + this._htmlElement.clientWidth,y:this.position.y + this._htmlElement.clientHeight}
}
Brainstorming.Node.prototype.getOnMousedownEvent = function(){
    var self = this;
    return function(){
        self.map.startMove(self);
    }
    
};
Brainstorming.Map.prototype.getOnMouseupEvent = function(){
    var self = this;
    return function(){
        self.finishMove();
    }
};

Brainstorming.Map.prototype.finishMove = function(){
    var node = this.draggedNode;
    if (!node) 
        return;
    this.draggetNode = null;
    if (node && !(node.position.x == node.positionOrig.x && node.position.y == node.positionOrig.y)) {
        node.moveTo(node.position);
        node.refresh();
    }
    node.render();
    this.render();
    this.moving = false;};
Brainstorming.Node.prototype.getDeleteIcon = function(){
    var icon = frameDoc.createElement('IMG');
    icon.src = ICON_PATH_DELETE;
    var self = this;
    Brainstorming.Util.addEventListener(icon, 'click', function(){
        self.confirmDelete()
    });
    return icon;
};
Brainstorming.Node.prototype.getEditIcon = function(){
    var icon = frameDoc.createElement('IMG');
    icon.src = ICON_PATH_EDIT;
    var self = this;
    Brainstorming.Util.addEventListener(icon, 'click', this.getLabelOnclickEvent());
    return icon;
};

var ICON_PATH_ADD = 'http://www.madin.jp/gadget/img/shape_square_add.png';
var ICON_PATH_DELETE = 'http://www.madin.jp/gadget/img/delete.png';
var ICON_PATH_COLOR = 'http://www.madin.jp/gadget/img/palette.png';
var ICON_PATH_SHAPE = 'http://www.madin.jp/gadget/img/heart.png';
var ICON_PATH_EDIT = 'http://www.madin.jp/gadget/img/pencil.png';

Brainstorming.Node.prototype.createAddChildIcon = function(){
    var icon = frameDoc.createElement('IMG');
    icon.title = 'new node';
    icon.src = ICON_PATH_ADD;
    var self = this;
    Brainstorming.Util.addEventListener(icon, 'click', function(){
        self.addChildNode()
    });
    return icon;
};
Brainstorming.Node.prototype.createColorIcon = function(){
    var icon = frameDoc.createElement('IMG');
    icon.src = ICON_PATH_COLOR;
    var self = this;
    
    Brainstorming.Util.addEventListener(icon, 'click', function(){
        self.map.showColorPicker(self, function(value){
            self.setColor(value);
        });
    });
    
    this.colorIcon = icon;
    return icon;
};
Brainstorming.Node.prototype.createShapeIcon = function(){
    var icon = frameDoc.createElement('DIV');
    icon.title = 'change shape';
    icon.className = 'iconContainer';
    var iconImage = frameDoc.createElement('IMG');
    iconImage.src = ICON_PATH_SHAPE;
    icon.appendChild(iconImage);
    var self = this;
    
    Brainstorming.Util.addEventListener(icon, 'click', function(){
        self.map.showShapePicker(self, function(value){
            self.setShape(value);
        });
    });
    this.shapeIcon = icon;
    return icon;
};
Brainstorming.Node.prototype.setShape = function(value){
    this.shape = value;
    this.map.updateWave('update', this.id, {
        shape: value
    });
};

Brainstorming.Node.prototype.setColor = function(value){
    this.color = value;
    this.map.updateWave('update', this.id, {
        color: value
    });
};

Brainstorming.Node.prototype.addChildNode = function(){
    var node = this.map.createNode({
        text: "New Node",
        position: {
            x: this.position.x + 50,
            y: this.position.y + 50
        },
        parentNodeId: this.id
    });
};


Brainstorming.Node.prototype.confirmDelete = function(){
    if (!this.parentNode) {
        alert("You can't delete the root node.");
    }
    else 
        if (this.childNodes && this.childNodes.length > 0) {
            alert("Please delete child nodes beforehand.");
        }
        else {
            if (window.confirm("Are you sure to delete this node?")) {
                this.remove();
            }
        }
};
Brainstorming.Node.prototype.removeChild = function(targetNode){
    var targetIndex = null;
    for (var i = 0, l = this.childNodes.length; i < l; i++) {
        if (this.childNodes[i] == targetNode) 
            targetIndex = i;
    }
    this.childNodes.splice(targetIndex, 1);
}
Brainstorming.Node.prototype.remove = function(){
    this.disposeFlg = true;
    this.map.updateWave('delete', this.id);
}
Brainstorming.Node.prototype.execDeleteCommand = function(){
    this.parentNode.removeChild(this);
    this.map.unregisterNode(this);
    this.destroy();
    this.map.render();
    
}

Brainstorming.Node.prototype.destroy = function(){
    this.map.unregisterNode(this);
    this._htmlElement.parentNode.removeChild(this._htmlElement);
}

Brainstorming.Node.prototype.getLabel = function(){
    var label = frameDoc.createElement('DIV');
    label.className = 'label';
    label.title = 'Click to edit';
    Brainstorming.Util.addEventListener(label, 'click', this.getLabelOnclickEvent());
    label.hide = function(){
        label.style.display = 'none';
    };
    label.show = function(){
        label.style.display = 'block';
    };
    return label;
};


Brainstorming.Node.prototype.getLabelOnclickEvent = function(){
    var self = this;
    return function(){
        self._label.hide();
        self._editor.show();
    }
}

Brainstorming.Node.prototype.getOnMouseoverEvent = function(){
    var self = this;
    return function(){
        self._menuPalette.show();
    }
}

Brainstorming.Node.prototype.getOnMouseoutEvent = function(){
    var self = this;
    return function(){
        self._menuPalette.hide();
    }
}

/**
 * Draw node and child nodes recursively
 * @param {Object} params
 */
Brainstorming.Node.prototype.drawLine = function(){
    this.connector.render();
    //Render recursively
    if (this.childNodes && this.childNodes.length > 0) {
        for (var i = 0, l = this.childNodes.length; i < l; i++) {
            this.childNodes[i].drawLine();
        }
    }
};
Brainstorming.Node.prototype.render = function(params){
    if (!this._drawn) {
        params.canvas.appendChild(this._htmlElement);
    }
    this._drawn = true;
    this._label.innerHTML = this.text;
    this.setPosition(this.position);

    //Render recursively
    if (this.childNodes && this.childNodes.length > 0) {
        for (var i = 0, l = this.childNodes.length; i < l; i++) {
            this.childNodes[i].render(params);
        }
    }
}
Brainstorming.Node.prototype.update = function(params, caller){
    if (params.text) {
        this.setText(params.text, caller)
    }
    if (params.x && params.y) {
        this.setPosition(params);
        this.refresh(caller);
    }
};
Brainstorming.Node.prototype.refresh = function(caller){
    this.connector.render();
    if (this.childNodes && this.childNodes.length > 0) {
        for (var i = 0, l = this.childNodes.length; i < l; i++) {
            this.childNodes[i].connector.render();
        }
    }
    this.map.onUpdateNode(this, caller);
};

Brainstorming.Node.prototype.moveTo = function(position){
    this.position = position;
    this.map.updateWave('update', this.id, {
        position: position
    });
}

Brainstorming.Node.prototype.setPosition = function(position){
    var prevPosition = this.position;
    this.position = position;
    this._htmlElement.style.left = position.x + 'px';
    this._htmlElement.style.top = position.y + 'px';
};


Brainstorming.Map.prototype.updateWave = function(eventType, id, params){
    var recentJsonStr = ({
        eventType: eventType,
        id: id,
        params: params,
        actorId: wave.getViewer().getId(),
        actorIconUrl: wave.getViewer().getThumbnailUrl()
    }).toJSONString();
    wave.getState().submitDelta({
        mind_recent: recentJsonStr,
        mind_tree: this.getDumpString()
    });
};

Brainstorming.Map.prototype.execCommand = function(commandJson){
    var obj = JSON.parse(commandJson);
    var targetNode = null;
    if ('update' == obj.eventType) {
        targetNode = this.nodeMap[obj.id];
        targetNode.execUpdateCommand(obj.params);
        targetNode.showActorIcon(obj.actorIconUrl);
    }
    else 
        if ('create' == obj.eventType) {
            targetNode = this.execCreateCommand(obj.id, obj.params);
            targetNode.showActorIcon(obj.actorIconUrl);
        }
        else 
            if ('delete' == obj.eventType) {
                targetNode = this.nodeMap[obj.id];
                targetNode.execDeleteCommand();
            }
};

Brainstorming.Map.prototype.getDumpString = function(){
    var dumpObjArray = new Array();
    for (id in this.nodeMap) {
        if ('function' == typeof(this.nodeMap[id])) 
            continue;
        if (this.nodeMap[id] && !this.nodeMap[id].disposeFlg) 
            dumpObjArray.push(this.nodeMap[id].getDumpObj());
    }
    var dumpString = dumpObjArray.toJSONString();
    return dumpString;
};

Brainstorming.Node.prototype.getDumpObj = function(){
    return {
        id: this.id,
        parentNodeId: ((this.parentNode) ? this.parentNode.id : null),
        text: this.text,
        position: this.position,
        shape: this.shape,
        color: this.color
    };
};

Brainstorming.Node.prototype.execUpdateCommand = function(params){
    if (params.text) {
        this.text = params.text;
        this._label.show();
        this._label.innerHTML = this.text;
        this._adjustLabelStyle();
        
    }
    if (params.position) {
        this.setPosition(params.position);
    }
    if (params.shape) {
        this.shape = params.shape;
        this._htmlElement.className = 'node ' + this.color + '_' + this.shape + Math.min(2, this.level);
    }
    
    if (params.color) {
        this.color = params.color;
        this._htmlElement.className = 'node ' + this.color + '_' + this.shape + Math.min(2, this.level);
    }
    this.render();
}
Brainstorming.Node.prototype.showActorIcon = function(url){
    this.map.actorIcon.src = url;
    with (this.map.actorIcon.style) {
        left = this.position.x - 10;
        top = this.position.y - 10;
        display = 'block';
    }
}
Brainstorming.Node.prototype.setText = function(newText, caller){
    this.text = newText;
    this.map.updateWave('update', this.id, {
        text: newText
    });
};
Brainstorming.Node.prototype._adjustLabelStyle = function(){
    var length = this.text.length; //FIXME (doesn't work)
    var size = 100 / Math.max(Math.min(length, 10), 2);
    this._label.style.fontSize = Math.ceil(size) + 'px';
};

Brainstorming.Node.prototype.getCenterPosition = function(){
    return {
        x: this.position.x + this._htmlElement.clientWidth / 2,
        y: this.position.y + this._htmlElement.clientHeight / 2
    };
}

Brainstorming.Connector = function(params){
    this.from = params.from;
    this.to = params.to;
    this.map = params.map;
    this.level = params.level;
};
Brainstorming.Connector.prototype.render = function(level){    if (this.from && this.to) {
        var fromPos = this.from.getCenterPosition();
        var toPos = this.to.getCenterPosition();
        var rootSize = Math.max(1, 4 - this.level) * 5;
        
        var _length = Math.max(1, Math.sqrt(Math.pow(fromPos.x - toPos.x, 2) + Math.pow(fromPos.y - toPos.y, 2)));
        var rootDeltaX = (fromPos.y - toPos.y) * rootSize / _length;
        var rootDeltaY = -(fromPos.x - toPos.x) * rootSize / _length;
        var rootPos0 = {
            x: fromPos.x + rootDeltaX,
            y: fromPos.y + rootDeltaY
        };
        var rootPos1 = {
            x: fromPos.x - rootDeltaX,
            y: fromPos.y - rootDeltaY
        };
        var opacity = Math.max(0.3, 1 - this.level * 0.2);
        
        var colorValue = this.map.colorPicker.getColorValue(this.to.color);
        this.map.lineArea.fillStyle = "rgba(" + colorValue.r + "," + colorValue.g + "," + colorValue.b + "," + opacity + ")";
        this.map.lineArea.beginPath();
        this.map.lineArea.moveTo(toPos.x, toPos.y);
        this.map.lineArea.lineTo(rootPos1.x, rootPos1.y);
        this.map.lineArea.lineTo(rootPos0.x, rootPos0.y);
        
        this.map.lineArea.closePath();
        this.map.lineArea.fill();
    }
};

/**
 * Utility
 */
Brainstorming.Util.addEventListener = function(element, eventType, func){
    if (element.addEventListener) {
        element.addEventListener(eventType, func, true);
    }
    else {
        if ('click' == eventType) 
            element.onclick = func;
        if ('dblclick' == eventType) 
            element.ondblclick = func;
        if ('mousedown' == eventType) 
            element.onmousedown = func;
        if ('mouseup' == eventType) 
            element.onmouseup = func;
    }
};

var NODE_SHAPE_LIST = ['oval', 'cloud', 'lightning'];

Brainstorming.ShapePicker = function(map){
    this.map = map;
    this.palette = frameDoc.createElement('DIV');
    this.palette.className = 'pickerPalette';
    this.palette.style.display = 'none';
    this.map.canvas.appendChild(this.palette);
    var self = this;
    for (var i = 0, l = NODE_SHAPE_LIST.length; i < l; i++) {
	var tipContainer = frameDoc.createElement('DIV');
        var tip = frameDoc.createElement('A');
	tip.className = 'paletteTip';
	tip.href = 'javascript:void(0)';
        var value = NODE_SHAPE_LIST[i];
        tip.innerHTML = value;
	tipContainer.appendChild(tip);
        this.palette.appendChild(tipContainer);
        Brainstorming.Util.addEventListener(tip, 'click', this.getClickAction(value))
    }
};
Brainstorming.ShapePicker.prototype.getClickAction = function(value){
    var self = this;
    return function(){
        self.palette.style.display = 'none';
        self._onSelectCallback(value);
    }
}
Brainstorming.ShapePicker.prototype.show = function(node, onSelectCallback){
    this.palette.style.display = 'block';
    var icon = node.shapeIcon;
    icon.parentNode.insertBefore(this.palette, icon.nextSibling);
    this._onSelectCallback = onSelectCallback;
};


var NODE_COLOR_LIST = [{
    name: 'black',
    r: 0,
    g: 0,
    b: 0
}, {
    name: 'red',
    r: 255,
    g: 0,
    b: 0
}, {
    name: 'purple',
    r: 255,
    g: 0,
    b: 255
}, {
    name: 'blue',
    r: 0,
    g: 0,
    b: 255
}, {
    name: 'cyan',
    r: 0,
    g: 255,
    b: 255
}, {
    name: 'green',
    r: 0,
    g: 255,
    b: 0
}, {
    name: 'yellow',
    r: 255,
    g: 255,
    b: 0
}];

Brainstorming.ColorPicker = function(map){
    this.map = map;
    this.palette = frameDoc.createElement('DIV');
    this.palette.className = 'pickerPalette';
    this.palette.style.display = 'none';
    this.map.canvas.appendChild(this.palette);
    
    this.colorMap = new Array();
    for (var i = 0, l = NODE_COLOR_LIST.length; i < l; i++) {
        var obj = NODE_COLOR_LIST[i];
        this.colorMap[obj.name] = obj;
    }
    var self = this;
    for (var i = 0, l = NODE_COLOR_LIST.length; i < l; i++) {
	var tipContainer = frameDoc.createElement('DIV');
        var tip = frameDoc.createElement('A');
	tip.className = 'paletteTip';
	tip.href = 'javascript:void(0)';
        var value = NODE_COLOR_LIST[i].name;
        tip.innerHTML = value;
	tipContainer.appendChild(tip);
        this.palette.appendChild(tipContainer);
        Brainstorming.Util.addEventListener(tip, 'click', this.getClickAction(value))
    }
};
Brainstorming.ColorPicker.prototype.getColorValue = function(name){
    return this.colorMap[name];
};
Brainstorming.ColorPicker.prototype.getClickAction = function(value){
    var self = this;
    return function(){
        self.palette.style.display = 'none';
        self._onSelectCallback(value);
    }
}
Brainstorming.ColorPicker.prototype.show = function(node, onSelectCallback){
    this.palette.style.display = 'block';
    var icon = node.colorIcon;
    icon.parentNode.insertBefore(this.palette, icon.nextSibling);
    this._onSelectCallback = onSelectCallback;
};

var NODE_SHAPE_LIST = ['oval', 'cloud', 'lightning'];

Brainstorming.ShapePicker = function(map){
    this.map = map;
    this.palette = frameDoc.createElement('DIV');
    this.palette.className = 'pickerPalette';
    this.palette.style.display = 'none';
    this.map.canvas.appendChild(this.palette);
    var self = this;
    for (var i = 0, l = NODE_SHAPE_LIST.length; i < l; i++) {
	var tipContainer = frameDoc.createElement('DIV');
        var tip = frameDoc.createElement('A');
	tip.className = 'paletteTip';
	tip.href = 'javascript:void(0)';
        var value = NODE_SHAPE_LIST[i];
        tip.innerHTML = value;
	tipContainer.appendChild(tip);
        this.palette.appendChild(tipContainer);
        Brainstorming.Util.addEventListener(tip, 'click', this.getClickAction(value))
    }
};
Brainstorming.ShapePicker.prototype = {
	getClickAction : function(value){
	    var self = this;
	    return function(){
	        self.palette.style.display = 'none';
	        self._onSelectCallback(value);
	    }
	},
	show: function(node, onSelectCallback){
		this.palette.style.display = 'block';
		var icon = node.shapeIcon;
		icon.parentNode.insertBefore(this.palette, icon.nextSibling);
		this._onSelectCallback = onSelectCallback;
	}
};
